/*     */ package com.zimbra.cs.server;
/*     */ 
/*     */ import com.google.common.base.Preconditions;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.io.IOException;
/*     */ import java.net.InetAddress;
/*     */ import java.net.Socket;
/*     */ import java.net.SocketException;
/*     */ import java.net.SocketTimeoutException;
/*     */ import java.nio.channels.AsynchronousCloseException;
/*     */ import javax.net.ssl.HandshakeCompletedEvent;
/*     */ import javax.net.ssl.HandshakeCompletedListener;
/*     */ import javax.net.ssl.SSLException;
/*     */ import javax.net.ssl.SSLSocket;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class ProtocolHandler
/*     */   implements Runnable
/*     */ {
/*     */   private final Log log;
/*     */   protected Socket connection;
/*     */   
/*     */   protected abstract boolean setupConnection(Socket paramSocket)
/*     */     throws IOException;
/*     */   
/*     */   protected abstract boolean authenticate()
/*     */     throws IOException;
/*     */   
/*     */   protected abstract boolean processCommand()
/*     */     throws Exception;
/*     */   
/*     */   protected abstract void dropConnection();
/*     */   
/*  82 */   private volatile boolean idle = true;
/*  83 */   private volatile boolean shuttingDown = false;
/*     */   
/*     */   protected abstract void notifyIdleConnection();
/*     */   
/*     */   public ProtocolHandler(TcpServer server) {
/*  88 */     this.server = server;
/*  89 */     this.log = server.getConfig().getLog();
/*     */   }
/*     */   
/*     */   protected void setIdle(boolean value) {
/*  93 */     this.idle = value;
/*     */   }
/*     */   
/*     */   private boolean getShuttingDown() {
/*  97 */     return this.shuttingDown;
/*     */   }
/*     */   
/*     */   private void setShuttingDown(boolean value) {
/* 101 */     this.shuttingDown = value;
/*     */   }
/*     */   
/*     */   void setConnection(Socket sock) {
/* 105 */     this.connection = sock;
/*     */   }
/*     */   
/*     */ 
/*     */   private final TcpServer server;
/*     */   private Thread handlerThread;
/*     */   public void run()
/*     */   {
/* 113 */     Preconditions.checkState(this.connection != null, "Connection can not be null when running ProtocolHandler");
/* 114 */     String remoteAddress = this.connection.getInetAddress().getHostAddress();
/*     */     
/* 116 */     this.handlerThread = Thread.currentThread();
/* 117 */     this.server.addActiveHandler(this);
/*     */     
/* 119 */     ZimbraLog.clearContext();
/*     */     try
/*     */     {
/* 122 */       this.connection.setSoTimeout(this.server.getConfigMaxIdleMilliSeconds());
/* 123 */       if ((this.connection instanceof SSLSocket)) {
/* 124 */         startHandshake((SSLSocket)this.connection);
/*     */       }
/*     */       
/* 127 */       if (setupConnection(this.connection)) {
/* 128 */         if (authenticate()) {
/* 129 */           processConnection();
/*     */         } else {
/* 131 */           this.log.info("Authentication failed for client %s", new Object[] { remoteAddress });
/*     */         }
/*     */       } else {
/* 134 */         this.log.info("Connection refused for client %s", new Object[] { remoteAddress });
/*     */       }
/*     */     } catch (SocketTimeoutException e) {
/* 137 */       ZimbraLog.addIpToContext(remoteAddress);
/* 138 */       this.log.debug("Idle timeout", e);
/* 139 */       notifyIdleConnection();
/*     */     } catch (AssertionError e) {
/* 141 */       this.log.error("This should not happen. Please file a bug.", e);
/*     */     } catch (OutOfMemoryError e) {
/* 143 */       Zimbra.halt("out of memory", e);
/*     */     } catch (Error e) {
/* 145 */       Zimbra.halt("Fatal error occurred while handling connection", e);
/*     */     } catch (Throwable e) {
/* 147 */       ZimbraLog.addIpToContext(remoteAddress);
/* 148 */       this.log.error("Exception occurred while handling connection", e);
/*     */     } finally {
/* 150 */       dropConnection();
/* 151 */       ZimbraLog.addIpToContext(remoteAddress);
/*     */       try {
/* 153 */         this.connection.close();
/*     */       } catch (IOException e) {
/* 155 */         if (this.log.isDebugEnabled()) {
/* 156 */           this.log.info("I/O error while closing connection", e);
/*     */         } else {
/* 158 */           this.log.info("I/O error while closing connection: %s", new Object[] { e.toString() });
/*     */         }
/*     */       } finally {
/* 161 */         ZimbraLog.clearContext();
/*     */       }
/*     */     }
/*     */     
/* 165 */     ZimbraLog.clearContext();
/* 166 */     this.server.removeActiveHandler(this);
/* 167 */     this.handlerThread = null;
/* 168 */     this.log.info("Handler exiting normally");
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   protected void startHandshake(final SSLSocket sock)
/*     */     throws IOException
/*     */   {
/* 177 */     sock.startHandshake();
/* 178 */     sock.addHandshakeCompletedListener(new HandshakeCompletedListener()
/*     */     {
/*     */       public void handshakeCompleted(HandshakeCompletedEvent event) {
/* 181 */         ProtocolHandler.this.hardShutdown("SSL renegotiation denied: " + sock);
/*     */       }
/*     */     });
/*     */   }
/*     */   
/*     */   private void processConnection() throws Exception {
/* 187 */     boolean cont = true;
/* 188 */     while ((cont) && (!getShuttingDown())) {
/*     */       try {
/* 190 */         cont = processCommand();
/* 191 */         setIdle(true);
/*     */       } catch (IOException e) {
/* 193 */         ZimbraLog.addIpToContext(this.connection.getInetAddress().getHostAddress());
/* 194 */         if (isSocketError(e)) {
/* 195 */           cont = false;
/* 196 */           if (getShuttingDown())
/*     */           {
/*     */ 
/* 199 */             this.log.debug("Shutdown in progress", e);
/* 200 */           } else if (this.log.isDebugEnabled())
/*     */           {
/*     */ 
/* 203 */             this.log.info("I/O error while processing connection", e);
/*     */           } else {
/* 205 */             this.log.info("I/O error while processing connection: " + e);
/*     */           }
/*     */         } else {
/* 208 */           throw e;
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static boolean isSocketError(IOException e) {
/* 215 */     return ((e instanceof SocketException)) || ((e instanceof SSLException)) || ((e instanceof AsynchronousCloseException));
/*     */   }
/*     */   
/*     */   void gracefulShutdown(String reason)
/*     */   {
/* 220 */     setShuttingDown(true);
/* 221 */     if (reason != null) {
/* 222 */       this.log.info(reason);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 230 */     if (this.idle) {
/* 231 */       hardShutdown(null);
/*     */     }
/*     */   }
/*     */   
/*     */   void hardShutdown(String reason) {
/* 236 */     setShuttingDown(true);
/* 237 */     if (reason != null) {
/* 238 */       this.log.info(reason);
/*     */     }
/* 240 */     if (!this.connection.isClosed()) {
/* 241 */       dropConnection();
/*     */       try {
/* 243 */         this.connection.close();
/*     */       } catch (IOException e) {
/* 245 */         this.log.info("Exception while closing connection", e);
/*     */       }
/*     */     }
/* 248 */     if (this.handlerThread != null) {
/* 249 */       this.handlerThread.interrupt();
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/server/ProtocolHandler.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */